package com.example.demo.utils.exportUtils;

import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.example.demo.common.ResultDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * HTTP请求工具类
 *
 * @author lilianxin@gogpay.cn
 * @date 2022-05-19 11:24
 */
@Component
public class HttpUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);

    private static HttpUtils httpUtils;

    @PostConstruct
    public void init() {
        httpUtils = this;
    }

    private final RestTemplate restTemplate;

    @Autowired
    public HttpUtils(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    /**
     * IP分隔符
     */
    private static final String IP_UTILS_FLAG = ",";
    /**
     * 未知IP地址
     */
    private static final String UNKNOWN = "unknown";
    /**
     * ipv6默认地址
     */
    private static final String LOCALHOST_IP = "0:0:0:0:0:0:0:1";
    /**
     * 本地回环地址
     */
    private static final String LOCALHOST_IP1 = "127.0.0.1";

    /**
     * 获取IP公网地址
     * <p>
     * 使用Nginx等反向代理软件， 则不能通过request.getRemoteAddr()获取IP地址
     * 如果使用了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP地址，X-Forwarded-For中第一个非unknown的有效IP字符串，则为真实IP地址
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ipAddress = StringUtils.EMPTY;
        try {
            // 以下两个获取在k8s中，将真实的客户端IP，放到了x-Original-Forwarded-For。而将WAF的回源地址放到了 x-Forwarded-For了。
            ipAddress = request.getHeader("X-Original-Forwarded-For");
            if (StringUtils.isEmpty(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("X-Forwarded-For");
            }
            // 获取nginx等代理的ip
            if (StringUtils.isEmpty(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("x-forwarded-for");
            }
            if (StringUtils.isEmpty(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ipAddress) || ipAddress.length() == 0 || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("HTTP_CLIENT_IP");
            }
            if (StringUtils.isEmpty(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            // 兼容k8s集群获取ip
            if (StringUtils.isEmpty(ipAddress) || UNKNOWN.equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                if (LOCALHOST_IP1.equalsIgnoreCase(ipAddress) || LOCALHOST_IP.equalsIgnoreCase(ipAddress)) {
                    try {
                        // 根据网卡取本机配置的IP
                        ipAddress = InetAddress.getLocalHost().getHostAddress();
                    } catch (UnknownHostException e) {
                        LOGGER.error("根据网卡取本机配置的IP异常，异常信息: ", e);
                    }
                }
            }
            // 使用nginx多层代理会出现多个ip 第一个为真实ip地址
            if (!StringUtils.isEmpty(ipAddress) && ipAddress.indexOf(IP_UTILS_FLAG) > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(IP_UTILS_FLAG));
            }
        } catch (Exception e) {
            LOGGER.error("获取IP地址异常，异常信息：", e);
        }
        return ipAddress;
    }

    /**
     * 发送post请求
     *
     * @param url        请求地址
     * @param request    请求参数
     * @param msg        来源
     * @param resultType 返回值类型关联
     * @param <T>        返回值类型
     * @return 返回结果
     */
    public static <T extends ResultDTO> T sendPost(String url, Object request, String msg, TypeReference<T> resultType) {
        LOGGER.debug("【发送HTTP POST请求】来源：{},请求地址：{},请求参数：{}", msg, url, JSON.toJSONString(request));
        T resultDTO = null;
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<?> req = new HttpEntity<>(JSON.toJSONString(request), headers);
            JSONObject resultJson = httpUtils.restTemplate.postForObject(url, req, JSONObject.class);
            resultDTO = JSONObject.parseObject(JSON.toJSONString(resultJson), resultType);
            LOGGER.debug("【发送HTTP POST请求】来源：{}，返回结果：{}", msg, JSON.toJSONString(resultDTO));
        } catch (Exception e) {
            LOGGER.error("【发送HTTP POST请求】发生异常，异常信息：{}", e.getMessage());
            e.printStackTrace();
        }
        return resultDTO;
    }

}
